package com.yichi.service;

import android.util.Log;

import com.jeremyliao.liveeventbus.LiveEventBus;
import com.yichi.YiChiApplication;
import com.yichi.biz_bean.DeviceOperInfo;
import com.yichi.device_bean.BatteryStore;
import com.yichi.device_bean.BatteryStoreType;
import com.yichi.device_bean.BmsParam;
import com.yichi.device_bean.BmsStatus;
import com.yichi.device_bean.DeviceInfo;
import com.yichi.device_bean.PcbDataInfo;
import com.yichi.global.AppConfig;
import com.yichi.global.EventDef;
import com.yichi.global.LocalStorageKey;
import com.yichi.util.BeanUtil;
import com.yichi.util.JsonUtil;
import com.yichi.util.SPUtil;
import com.yichi.util.StringUtil;
import com.yichi.util.Utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 换电柜设备服务
 */
public class DeviceService {
    private final static String TAG = "DeviceService";

    //设备信息
    public DeviceInfo deviceInfo = null;

    //电池仓
    public List<BatteryStore> batteryStoreList = new ArrayList<>();//电池仓集合
    public List<BatteryStore> inputStoreList = new ArrayList<>();//3个存
    public List<BatteryStore> outputStoreList = new ArrayList<>();//3个取
    public List<BatteryStore> storageStoreList = new ArrayList<>();//20个存储区
    public List<BatteryStore> rechargeStoreList = new ArrayList<>();//3个充电区
    public List<BatteryStore> faultStoreList = new ArrayList<>();//1个故障区

    //充电仓
    public Integer rechargeStoreStartIndex = 27;
    public Integer rechargeStoreCount = 3;

    /**
     * 电柜当前操作信息
     */
    private DeviceOperInfo deviceOperInfo = null;

    /**
     * 单例模式
     */
    public static DeviceService inst = new DeviceService();

    private DeviceService() {

    }

    //保证DeviceOperInfo读写安全
    public synchronized DeviceOperInfo getDeviceOperInfo() {
        return deviceOperInfo;
    }

    public synchronized void setDeviceOperInfo(DeviceOperInfo deviceOperInfo) {
        this.deviceOperInfo = deviceOperInfo;
    }

    public void init() {
        initBatteryStoreList();
    }

    //初始化电池仓数据
    public void initBatteryStoreList() {
        this.batteryStoreList = getData();
        if (this.batteryStoreList.isEmpty()) {
            this.initDefaultBatteryStoreList();
            saveData();
        } else {
            this.procBatteryStoreList(this.batteryStoreList);
        }
    }

    //获取数据
    public List<BatteryStore> getData() {
        String s = SPUtil.get(YiChiApplication.application, LocalStorageKey.KEY_BATTERY_STORE_LIST, "");
        if (StringUtil.isEmpty(s)) {
            List<BatteryStore> list = new ArrayList<>();
            return list;
        } else {
            List<BatteryStore> list = JsonUtil.parseArray(s, BatteryStore.class);
            if (list == null) {
                list = new ArrayList<>();
            }
            return list;
        }
    }

    //清除数据
    public void clearData() {
        this.batteryStoreList = new ArrayList<>();
        saveData();
//        SPUtil.remove(YiChiApplication.application, LocalStorageKey.KEY_BATTERY_STORE_LIST);
    }

    //保存数据
    public void saveData() {
        String jsonString = JsonUtil.toJSONString(this.batteryStoreList);
        SPUtil.set(YiChiApplication.application, LocalStorageKey.KEY_BATTERY_STORE_LIST, jsonString);
    }

    /**
     * 处理电池仓数据
     */
    private void procBatteryStoreList(List<BatteryStore> list) {
        for (int i = 0, j = list.size(); i < j; i++) {
            BatteryStore batteryStore = list.get(i);
            if (batteryStore.getStoreType().equals(BatteryStoreType.battery_store_type_input)) {
                this.inputStoreList.add(batteryStore);
            } else if (batteryStore.getStoreType().equals(BatteryStoreType.battery_store_type_output)) {
                this.outputStoreList.add(batteryStore);
            } else if (batteryStore.getStoreType().equals(BatteryStoreType.battery_store_type_storage)) {
                this.storageStoreList.add(batteryStore);
            } else if (batteryStore.getStoreType().equals(BatteryStoreType.battery_store_type_recharge)) {
                this.rechargeStoreList.add(batteryStore);
                if (this.rechargeStoreStartIndex == null) {
                    this.rechargeStoreStartIndex = batteryStore.getStoreNo();
                }
            } else if (batteryStore.getStoreType().equals(BatteryStoreType.battery_store_type_fault)) {
                this.faultStoreList.add(batteryStore);
            }
        }
        this.rechargeStoreCount = this.rechargeStoreList.size();
    }

    /**
     * 初始默认电池仓数据
     */
    private void initDefaultBatteryStoreList() {
        //3个存
        for (int i = 1; i <= 3; i++) {
            BatteryStore batteryStore = new BatteryStore(i, BatteryStoreType.battery_store_type_input);
            inputStoreList.add(batteryStore);
        }
        //3个取
        for (int i = 4; i <= 6; i++) {
            BatteryStore batteryStore = new BatteryStore(i, BatteryStoreType.battery_store_type_output);
            outputStoreList.add(batteryStore);
        }
        //20个存储
        for (int i = 7; i <= 26; i++) {
            BatteryStore batteryStore = new BatteryStore(i, BatteryStoreType.battery_store_type_storage);
            storageStoreList.add(batteryStore);
        }
        //3个充电
        for (int i = 27; i <= 29; i++) {
            BatteryStore batteryStore = new BatteryStore(i, BatteryStoreType.battery_store_type_recharge);
            rechargeStoreList.add(batteryStore);
        }
        rechargeStoreStartIndex = 27;
        rechargeStoreCount = 3;
        //1个故障
        for (int i = 30; i <= 30; i++) {
            BatteryStore batteryStore = new BatteryStore(i, BatteryStoreType.battery_store_type_fault);
            faultStoreList.add(batteryStore);
        }

        //合并
        batteryStoreList.addAll(inputStoreList);
        batteryStoreList.addAll(outputStoreList);
        batteryStoreList.addAll(storageStoreList);
        batteryStoreList.addAll(rechargeStoreList);
        batteryStoreList.addAll(faultStoreList);
    }

    /**
     * 启动提交平台任务
     * 定时5秒执行
     */
    public void startSubmitPlatformOutputStoreInfoTask() {
        // 启动任务：任务执行完后等待5秒再执行下一次
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleWithFixedDelay(() -> {
            submitPlatformOutputStoreInfoTask();
        }, 0, 5, TimeUnit.SECONDS); // 初始延迟0秒，任务结束后等5秒再执行
    }

    /**
     * 提交给平台取电仓信息
     * 有变化执行
     * {
     * "response": "output_storeinfo"， // 维护
     * "cabinetNum": "nzh001"，// 机柜编号
     * "info":[
     * {
     * storeNo:4,
     * hasBattery:true,
     * batteryNo:"电池编号",
     * batterySoc:"电池电量",
     * batteryMileage:"电池里程",
     * },
     * {
     * storeNo:5,
     * hasBattery:true,
     * batteryNo:"电池编号",
     * batterySoc:"电池电量",
     * batteryMileage:"电池里程",
     * },
     * {
     * storeNo:6,
     * hasBattery:true,
     * batteryNo:"电池编号",
     * batterySoc:"电池电量",
     * batteryMileage:"电池里程",
     * }
     * ],
     * }
     */
    private void submitPlatformOutputStoreInfoTask() {
        try {
            Map<String, Object> result = new HashMap<>();
            result.put("response", "output_storeinfo");
            result.put("cabinetNum", AppConfig.DEVICE_ID);

            List<Map<String, Object>> list = new ArrayList<>();
            for (BatteryStore batteryStore : this.outputStoreList) {
                Map<String, Object> map = new HashMap<>();
                map.put("storeNo", batteryStore.getStoreNo());
                map.put("hasBattery", batteryStore.getHasBattery());
                map.put("batteryNo", batteryStore.getBatteryNo());
                map.put("batterySoc", batteryStore.getBatterySoc());
                map.put("batteryMileage", batteryStore.getBatteryMileage());
                list.add(map);
            }
            for (BatteryStore batteryStore : this.inputStoreList) {
                Map<String, Object> map = new HashMap<>();
                map.put("storeNo", batteryStore.getStoreNo());
                map.put("hasBattery", batteryStore.getHasBattery());
                map.put("batteryNo", batteryStore.getBatteryNo());
                map.put("batterySoc", batteryStore.getBatterySoc());
                map.put("batteryMileage", batteryStore.getBatteryMileage());
                list.add(map);
            }
            result.put("info", list);

            Map<String, Integer> totalMap = totalStoreInfoTask();
            result.put("total", totalMap);

            String jsonString = JsonUtil.toJSONString(result);
            Log.i(TAG, "给平台发送：" + jsonString);
            MqttService.inst.sendMsg(jsonString);
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
        }
    }

    /**
     * 统计下可存，可取，充电中数量
     */
    private Map<String, Integer> totalStoreInfoTask() {
        //存储区
        long storageNotEmptyCount = this.storageStoreList.stream().filter(item -> item.getHasBattery()).count();
        long storageEmptyCount = this.storageStoreList.stream().filter(item -> !item.getHasBattery()).count();
        //充电区
        long rechargeNotEmptyCount = this.rechargeStoreList.stream().filter(item -> item.getHasBattery()).count();
        long rechargeEmptyCount = this.rechargeStoreList.stream().filter(item -> !item.getHasBattery()).count();
        //取电口
        long outputNotEmptyCount = this.outputStoreList.stream().filter(item -> item.getHasBattery()).count();
        long outputEmptyCount = this.outputStoreList.stream().filter(item -> !item.getHasBattery()).count();

        int kc = (int) (storageEmptyCount + outputEmptyCount);//加取的空口
        int kq = (int) (storageNotEmptyCount + outputNotEmptyCount);
        int cdz = (int) rechargeNotEmptyCount;
        Map<String, Integer> map = new HashMap<>();
        map.put("kc", kc);//可存
        map.put("kq", kq);//可取
        map.put("cdz", cdz);//充电中
        map.put("ky", kq);//可用

        LiveEventBus.get(EventDef.EVENT_STORE_TOTAL_TASK, Map.class).post(map);
        return map;
    }

    /**
     * 启动处理调度电池任务
     */
    public void startHandleDispachBatteryTask() {
        // 启动任务：任务执行完后等待5秒再执行下一次
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleWithFixedDelay(() -> {
            handleDispachBatteryTask();
        }, 5, 5, TimeUnit.SECONDS); // 初始延迟5秒，任务结束后等5秒再执行
    }

    /**
     * 处理调度电池任务
     * 移动电池
     */
    private void handleDispachBatteryTask() {
        TaskMoveBean taskMoveBean = TaskDispachQueue.inst.getTaskNonBlocking();
        if (taskMoveBean == null) {
            return;
        }

        Log.i(TAG, String.format("开始移动电池：%s——>%s", taskMoveBean.getSrcStore().getStoreNo(), taskMoveBean.getTarStore().getStoreNo()));

        //1 设置数据
        taskMoveBean.getSrcStore().setLockStatus(2);
        taskMoveBean.getTarStore().setLockStatus(2);

        //2 移动状态清0
        PlcService.inst.resetMoveStatus();

        //3 置前工作
        switch (taskMoveBean.getSrcStore().getStoreType()) {
            case BatteryStoreType.battery_store_type_input:
                break;
            case BatteryStoreType.battery_store_type_output:
                break;
            case BatteryStoreType.battery_store_type_storage:
                break;
            case BatteryStoreType.battery_store_type_recharge:
                //充电仓移走，断电
                PcbService.inst.powerOff(taskMoveBean.getSrcStore().getStoreNo());
                break;
            case BatteryStoreType.battery_store_type_fault:
                break;
        }

        //4 发送移动指令
        PlcService.inst.handleMoveBattery(taskMoveBean.getSrcStore().getStoreNo(), taskMoveBean.getTarStore().getStoreNo());

        //5 检查是否移动完成
        boolean batteryMoveComplete = PlcService.inst.isBatteryMoveComplete();
        if (!batteryMoveComplete) {
            Log.i(TAG, String.format("电池移动出现严重错误，两个仓被锁死，src：%s，tar：%s", taskMoveBean.getSrcStore().getStoreNo(), taskMoveBean.getTarStore().getStoreNo()));
            return;
        }

        //6 置后工作
        switch (taskMoveBean.getTarStore().getStoreType()) {
            case BatteryStoreType.battery_store_type_input:
                break;
            case BatteryStoreType.battery_store_type_output:
                break;
            case BatteryStoreType.battery_store_type_storage:
                break;
            case BatteryStoreType.battery_store_type_recharge:
                //移动到充电仓，上电
                PcbService.inst.powerOn(taskMoveBean.getTarStore().getStoreNo());
                break;
            case BatteryStoreType.battery_store_type_fault:
                break;
        }

        //7 设置数据
        BeanUtil.copyBatteryStore(taskMoveBean.getSrcStore(), taskMoveBean.getTarStore());
        BeanUtil.setBatteryStoreEmpty(taskMoveBean.getSrcStore());
        taskMoveBean.getSrcStore().setLockStatus(0);
        taskMoveBean.getTarStore().setLockStatus(0);

        //8 保存数据
        saveData();
    }

    /**
     * 启动处理调度电池任务
     */
    public void startCheckDispachBatteryTask() {
        // 启动任务：任务执行完后等待5秒再执行下一次
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleWithFixedDelay(() -> {
            checkDispachBatteryTask();
        }, 5, 3, TimeUnit.SECONDS); // 初始延迟5秒，任务结束后等5秒再执行
    }

    /**
     * 检查调度电池任务
     */
    private void checkDispachBatteryTask() {
        //1 存电口。移动到存储区或充电区
        for (BatteryStore inputStore : this.inputStoreList) {
            BatteryStore emptyRechargeStore = getEmptyRechargeStore();
            BatteryStore emptyStorageStore = getEmptyStorageStore();
            BatteryStore emptyOutputStore = getEmptyOutputStore();

            if (emptyRechargeStore == null && emptyStorageStore == null && emptyOutputStore == null) {
                break;//没有存放区
            }

            if (inputStore.getHasBattery() && inputStore.getLockStatus().equals(0) && !inputStore.getDoorOpen()) {

                //去平台请求下bms信息
                Map<String, Object> bmsMap = PlatformService.getBmsInfo(inputStore.getBatteryNo());
                if (bmsMap != null) {
                    BmsParam bmsParam = (BmsParam) bmsMap.get("bmsParam");
                    BmsStatus bmsStatus = (BmsStatus) bmsMap.get("bmsStatus");
                    inputStore.setBmsParam(bmsParam);
                    inputStore.setBmsStatus(bmsStatus);
                    //计算
                    Integer soc = bmsParam.getSoc();
                    Integer soh = bmsParam.getSoh();
                    float lc = Utils.getMileage(soc, soh);
                    inputStore.setBatterySoc(soc);
                    inputStore.setBatteryMileage(lc);
                } else {
                    //如果没获取到，设置为满电
                    inputStore.setBmsParam(null);
                    inputStore.setBmsStatus(null);
                    inputStore.setBatterySoc(100);
                    inputStore.setBatteryMileage(45F);
                }

                BatteryStore tarStore = null;
                if (inputStore.getBatterySoc() >= AppConfig.RECHARGE_SOC_LIMIT) {
                    //电满的。优先给取点口
                    if (emptyOutputStore != null) {
                        tarStore = emptyOutputStore;
                    } else {
                        tarStore = emptyStorageStore;
                    }
                } else {
                    //电不满
                    tarStore = emptyRechargeStore;
                }

                if (tarStore == null) {
                    continue;//没有存放区
                }

                tarStore.setLockStatus(1);
                inputStore.setLockStatus(1);

                TaskMoveBean taskMoveBean = new TaskMoveBean();
                taskMoveBean.setMoveType(TaskMoveType.task_move_src_input);
                taskMoveBean.setSrcStore(inputStore);
                taskMoveBean.setTarStore(tarStore);
                TaskDispachQueue.inst.addTaskNonBlocking(taskMoveBean);
            }
        }
        //2 取电口。补充电池移动
        for (BatteryStore outputStore : this.outputStoreList) {
            //存储区没电池
            BatteryStore notEmptyStorageStore = getNotEmptyStorageStore();
            if (notEmptyStorageStore == null) {
                break;
            }

            if (!outputStore.getHasBattery() && outputStore.getLockStatus().equals(0) && !outputStore.getDoorOpen()) {
                notEmptyStorageStore.setLockStatus(1);
                outputStore.setLockStatus(1);

                TaskMoveBean taskMoveBean = new TaskMoveBean();
                taskMoveBean.setMoveType(TaskMoveType.task_move_src_output);
                taskMoveBean.setSrcStore(notEmptyStorageStore);
                taskMoveBean.setTarStore(outputStore);
                TaskDispachQueue.inst.addTaskNonBlocking(taskMoveBean);
            }
        }
        //3 充电。充满移动
        for (BatteryStore rechargeStore : this.rechargeStoreList) {
            //没有空存储仓
            BatteryStore emptyStorageStore = getEmptyStorageStore();
            if (emptyStorageStore == null) {
                break;
            }

            if (rechargeStore.getHasBattery() && rechargeStore.getLockStatus().equals(0)) {
                PcbDataInfo pcbDataInfo = PcbService.inst.queryDataInfo(rechargeStoreStartIndex, rechargeStoreCount);
                if (pcbDataInfo == null || pcbDataInfo.getBmsParamMap() == null) {
                    continue;
                }
                BmsParam bmsParam = pcbDataInfo.getBmsParamMap().get(rechargeStore.getStoreNo());
                if (bmsParam == null) {
                    continue;
                }
                if (bmsParam.getSoc() < AppConfig.RECHARGE_SOC_LIMIT) {
                    continue;
                }

                emptyStorageStore.setLockStatus(1);
                rechargeStore.setLockStatus(1);

                TaskMoveBean taskMoveBean = new TaskMoveBean();
                taskMoveBean.setMoveType(TaskMoveType.task_move_src_recharge);
                taskMoveBean.setSrcStore(rechargeStore);
                taskMoveBean.setTarStore(emptyStorageStore);
                TaskDispachQueue.inst.addTaskNonBlocking(taskMoveBean);
            }
        }
        //4 存储仓。待充电移动
        for (BatteryStore storageStore : this.storageStoreList) {
            //没有空充电仓
            BatteryStore emptyRechargeStore = getEmptyRechargeStore();
            if (emptyRechargeStore == null) {
                break;
            }

            if (storageStore.getHasBattery() && storageStore.getLockStatus().equals(0)) {
                //不需要充电
                if (storageStore.getBatterySoc() >= AppConfig.RECHARGE_SOC_LIMIT) {
                    continue;
                }

                emptyRechargeStore.setLockStatus(1);
                storageStore.setLockStatus(1);

                TaskMoveBean taskMoveBean = new TaskMoveBean();
                taskMoveBean.setMoveType(TaskMoveType.task_move_src_storage);
                taskMoveBean.setSrcStore(storageStore);
                taskMoveBean.setTarStore(emptyRechargeStore);
                TaskDispachQueue.inst.addTask(taskMoveBean);
            }
        }
    }

    /**
     * 根据编号获取电池仓
     *
     * @param storeNo
     * @return
     */
    public BatteryStore getBatteryStoreByStoreNo(Integer storeNo) {
        BatteryStore batteryStore = this.batteryStoreList.get(storeNo - 1);
        return batteryStore;
    }

    /**
     * 获取一个空的存储仓
     */
    public BatteryStore getEmptyStorageStore() {
        BatteryStore batteryStore = this.storageStoreList.stream()
                .filter(item -> !item.getHasBattery() && item.getLockStatus().equals(0))
                .findFirst()
                .orElse(null);
        return batteryStore;
    }

    /**
     * 获取一个非空的存储仓
     */
    public BatteryStore getNotEmptyStorageStore() {
        BatteryStore batteryStore = this.storageStoreList.stream()
                .filter(item -> item.getHasBattery() && item.getLockStatus().equals(0))
                .findFirst()
                .orElse(null);
        return batteryStore;
    }

    /**
     * 获取一个空的充电仓
     */
    public BatteryStore getEmptyRechargeStore() {
        BatteryStore batteryStore = this.rechargeStoreList.stream()
                .filter(item -> !item.getHasBattery() && item.getLockStatus().equals(0))
                .findFirst()
                .orElse(null);
        return batteryStore;
    }

    /**
     * 获取一个空的故障仓
     */
    public BatteryStore getEmptyFaultStore() {
        BatteryStore batteryStore = this.batteryStoreList.stream()
                .filter(item -> item.getStoreType().equals(BatteryStoreType.battery_store_type_fault) && !item.getHasBattery())
                .findFirst()
                .orElse(null);
        return batteryStore;
    }

    /**
     * 获取一个空的取电仓
     *
     * @return
     */
    public BatteryStore getEmptyOutputStore() {
        BatteryStore batteryStore = this.outputStoreList.stream()
                .filter(item -> !item.getHasBattery() && item.getLockStatus().equals(0))
                .findFirst()
                .orElse(null);
        return batteryStore;
    }

    /**
     * 获取 存/取 仓列表
     *
     * @return
     */
    public List<BatteryStore> getInputAndOutputStoreList() {
        List<BatteryStore> storeList = batteryStoreList.stream()
                .filter(item -> item.getStoreType().equals(BatteryStoreType.battery_store_type_input) || item.getStoreType().equals(BatteryStoreType.battery_store_type_output))
                .collect(Collectors.toList());
        return storeList;
    }

    /**
     * 获取 存电仓 列表
     *
     * @return
     */
    public List<BatteryStore> getInputStoreList() {
        List<BatteryStore> storeList = batteryStoreList.stream()
                .filter(item -> item.getStoreType().equals(BatteryStoreType.battery_store_type_input))
                .collect(Collectors.toList());
        return storeList;
    }

    /**
     * 获取 取电仓 列表
     *
     * @return
     */
    public List<BatteryStore> getOutputStoreList() {
        List<BatteryStore> storeList = batteryStoreList.stream()
                .filter(item -> item.getStoreType().equals(BatteryStoreType.battery_store_type_output))
                .collect(Collectors.toList());
        return storeList;
    }

    /**
     * 随机获取一个存电仓
     */
    public BatteryStore getRandomInputStore() {
//        List<BatteryStore> list = getInputStoreList();
//        int rand = new Random().nextInt(list.size());
//        return list.get(rand);

        //测试代码
        BatteryStore batteryStoreByStoreNo = getBatteryStoreByStoreNo(2);
        if (!batteryStoreByStoreNo.getHasBattery() && StringUtil.isEmpty(batteryStoreByStoreNo.getBatteryNo(), true) && batteryStoreByStoreNo.getLockStatus().equals(0)) {
            return batteryStoreByStoreNo;
        } else {
            return null;
        }
    }

    /**
     * 随机获取一个有电池的取电仓
     */
    public BatteryStore getRandomOutputStoreHas() {
//        List<BatteryStore> list = this.outputStoreList.stream()
//                .filter(item -> item.getHasBattery() && item.getLockStatus().equals(0))
//                .collect(Collectors.toList());
//        if (list == null || !list.isEmpty()) {
//            return null;
//        } else {
//            int rand = new Random().nextInt(list.size());
//            return list.get(rand);
//        }

        //测试代码
        BatteryStore batteryStoreByStoreNo = getBatteryStoreByStoreNo(5);
        if (batteryStoreByStoreNo.getHasBattery() && StringUtil.isNotEmpty(batteryStoreByStoreNo.getBatteryNo(), true) && batteryStoreByStoreNo.getLockStatus().equals(0)) {
            return batteryStoreByStoreNo;
        } else {
            return null;
        }
    }

}
